package com.shockweb.common.virtualconn.connection;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.shockweb.common.log.LogManager;
import com.shockweb.common.virtualconn.factory.ConnentionFactoryWapper;

/**
 * 包装虚拟连接
 * @author 彭明华
 *
 */
public class VirtualConnectionWapper<T extends VirtualConnection> implements InvocationHandler{
	
	/**
	 * 关闭方法的名称
	 */
	private final static String CLOSE_METHOD_NAME = "close";
	
	/**
	 * toString方法的名称
	 */
	private final static String TOSTRING_METHOD_NAME = "toString";
	
	
	/**
	 * 虚拟连接
	 */
	private T virtualConnection = null;
	
	/**
	 * 连接工厂
	 */
	private ConnentionFactoryWapper<T> factoryWapper = null;
	
	/**
	 * 记录连接使用的线程
	 */
	private Thread thread = null;
			
	/**
	 * 构造方法
	 * @param virtualConnection
	 */
	public VirtualConnectionWapper(T virtualConnection,ConnentionFactoryWapper<T> factoryWapper){
		this.virtualConnection = virtualConnection;
		this.factoryWapper = factoryWapper;
	}
	/**
	 * 返回虚拟连接
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T getVirtualConnection(){
		//返回数据库连接client的接管类，以便截住close方法
		T conn = (T)Proxy.newProxyInstance(
				virtualConnection.getClass().getClassLoader(),virtualConnection.getClass().getInterfaces(),this);
		return conn;
	}
	
	/**
	 * 连接工厂
	 * @return
	 */
	public ConnentionFactoryWapper<T> getConnentionFactoryWapper(){
		return factoryWapper;
	}
	
	/**
	 * 测试连接的有效性
	 * @return
	 */
	public boolean check(){
		return virtualConnection.check();
	}
	
	/**
	 * 使用时间
	 */
	public long usedTime = -1;
	/**
	 * 连接是否可用
	 * @return
	 */
	public boolean isUsed(){
		return usedTime!=-1;
	}
	
	/**
	 * 立即回收连接
	 */
	public void retrieve(){
		retrieve(-1);
	}
	
	/**
	 * 回收超过time时长的连接
	 */
	public void retrieve(long time){
		if(usedTime>0 && System.currentTimeMillis()-usedTime>=time){
			this.usedTime = -1;
			this.thread = null;
			LogManager.warn(this.getClass(), "VirtualConnectionWapper '" + this + "' 强制回收");
		}
	}
	
	/**
	 * 设置连接被使用时间和使用的线程
	 */
	public void used() {
		this.usedTime = System.currentTimeMillis();
		this.thread = Thread.currentThread();
	}
	
	/**
	 * 关闭连接
	 * @throws Exception
	 */
	public void close() throws Exception{
		virtualConnection.close();
	}
	
	/**
	 * 实现InvocationHandler.invoke接口
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object obj = null;
		if(TOSTRING_METHOD_NAME.equals(method.getName())){
			try{
				obj = method.invoke(virtualConnection, args);
			}catch(InvocationTargetException e){
				if(e.getCause()!=null){
					throw e.getCause();
				}
			}
		}else if(isUsed() || thread==Thread.currentThread()){
			//判断是否调用了close的方法，如果调用close方法则把连接置为无用状态
			if(CLOSE_METHOD_NAME.equals(method.getName())){
				usedTime = -1;
				thread = null;
			}else{
				try{
					obj = method.invoke(virtualConnection, args);
				}catch(InvocationTargetException e){
					if(e.getCause()!=null){
						throw e.getCause();
					}
				}
			}
		}else{
			throw new Exception("Connection is closed");
		}
		return obj;
	}
}
